package cn.itcast.service.cargo.impl;

import cn.itcast.dao.cargo.*;
import cn.itcast.domain.cargo.*;
import cn.itcast.service.cargo.ExportService;
import cn.itcast.vo.ExportProductResult;
import cn.itcast.vo.ExportResult;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

// com.alibaba.dubbo.config.annotation.Service
@Service(timeout = 100000) 
public class ExportServiceImpl implements ExportService {

    /* 注入报运单信息*/
    @Autowired
    private ExportDao exportDao;
    @Autowired
    private ExportProductDao exportProductDao;
    @Autowired
    private ExtEproductDao extEproductDao;

    /*注入购销合同信息*/
    // 注入购销合同
    @Autowired
    private ContractDao contractDao;
    // 注入购销合同的货物
    @Autowired
    private ContractProductDao contractProductDao;
    // 注入购销合同的货物的附件
    @Autowired
    private ExtCproductDao extCproductDao;

    @Override
    public PageInfo<Export> findByPage(ExportExample exportExample, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Export> list = exportDao.selectByExample(exportExample);
        return new PageInfo<>(list);
    }

    @Override
    public Export findById(String id) {
        return exportDao.selectByPrimaryKey(id);
    }

    @Override
    public void save(Export export) {
        //1. 设置报运单id
        export.setId(UUID.randomUUID().toString());

        //2. 获取购销合同的id，多个id用逗号隔开
        String contractIds = export.getContractIds();
        if (contractIds == null) {
            throw new RuntimeException("购销合同的id为NULL，异常！");
        }

        //3. 处理报运单的合同号，数据来自于购销合同的合同号。多个合同号用空格隔开。
        String[] contractIdArray = contractIds.split(",");
        List<String> contractIdList =  Arrays.asList(contractIdArray);
        // 根据购销合同的id查询
        ContractExample contractExample = new ContractExample();
        contractExample.createCriteria().andIdIn(contractIdList);
        List<Contract> contractList = contractDao.selectByExample(contractExample);
        // 保存报运单中的合同号，多个合同号用空格隔开
        String contractNos = "";
        if (contractList != null && contractList.size() > 0) {
            for (Contract contract : contractList) {// 123 45
                contractNos += contract.getContractNo() + " ";
                //4. 合同列表，选中的购销合同，生成报运单后，需求修改购销合同的状态为2，表示已生成报运
                contract.setState(2);
                contractDao.updateByPrimaryKeySelective(contract);
            }
        }
        // 设置报运单的合同号 (通过String类的trim()方法去掉前后空格)
        export.setCustomerContract(contractNos.trim());


        //5. 根据购销合同，查询其下的所有货物
        ContractProductExample cpExample = new ContractProductExample();
        // select * from co_contract_product where contract_id in (1,2)
        cpExample.createCriteria().andContractIdIn(contractIdList);
        List<ContractProduct> contractProductList = contractProductDao.selectByExample(cpExample);
        // 创建一个map，key是货物id，value是商品id
        Map<String,String> idMap = new HashMap<>();
        //6. 【保存报运单的商品，数据来源于'购销合同的货物'】
        if (contractProductList != null && contractProductList.size() > 0) {
            for (ContractProduct contractProduct : contractProductList) {
                // 创建商品对象
                ExportProduct exportProduct = new ExportProduct();
                // 封装商品对象: 对象拷贝，导入org.springframework.beans
                // 注意：不要导错包，如果导入apache的包参数顺序刚好相反
                // 参数1：source，数据源，有数据的对象
                // 参数2：目标， 要拷贝到的目标对象
                BeanUtils.copyProperties(contractProduct,exportProduct);
                // 设置商品id
                exportProduct.setId(UUID.randomUUID().toString());
                // 设置商品关联的报运单id 【重要】
                exportProduct.setExportId(export.getId());

                // 保存商品对象
                exportProductDao.insertSelective(exportProduct);

                // 保存货物id、商品id（后面保存商品附件时候，需要指定哪个商品的附件）
                idMap.put(contractProduct.getId(),exportProduct.getId());
            }
        }

        //7. 根据购销合同，查询其下的所有附件
        ExtCproductExample extCproductExample = new ExtCproductExample();
        extCproductExample.createCriteria().andContractIdIn(contractIdList);
        List<ExtCproduct> extCproductList = extCproductDao.selectByExample(extCproductExample);
        //8. 【保存报运单的附件，数据来源于'购销合同的附件'】
        if (extCproductList != null && extCproductList.size() > 0) {
            for (ExtCproduct extCproduct : extCproductList) {
                // 创建报运单附件对象
                ExtEproduct extEproduct = new ExtEproduct();
                // 封装报运单附件对象
                BeanUtils.copyProperties(extCproduct,extEproduct);
                extEproduct.setId(UUID.randomUUID().toString());
                extEproduct.setExportId(export.getId());
                /*
                 * 设置商品id
                 * 已知条件： 货物id  extCproduct.getContractProductId()
                 * 求：      商品id
                 */
                // 获取货物id
                String contractProductId = extCproduct.getContractProductId();
                // 根据货物id，获取商品id并设置到附件中
                extEproduct.setExportProductId(idMap.get(contractProductId));

                // 保存报运单附件对象
                extEproductDao.insertSelective(extEproduct);
            }
        }

        //9. 【保存报运单】
        // 设置报运单的状态
        export.setState(0);
        // 设置商品的数量 (5)
        export.setProNum(contractProductList.size());
        // 设置商品附件的数量 (7)
        export.setExtNum(extCproductList.size());
        // 最终，保存报运单
        exportDao.insertSelective(export);
    }

    @Override
    public void update(Export export) {
        //1. 修改报运单
        exportDao.updateByPrimaryKeySelective(export);

        //2. 修改报运单的商品
        List<ExportProduct> exportProducts = export.getExportProducts();
        if (exportProducts != null && exportProducts.size() > 0) {
            for (ExportProduct exportProduct : exportProducts) {
                // 修改报运单商品 (动态sql)
                exportProductDao.updateByPrimaryKeySelective(exportProduct);
            }
        }
    }

    @Override
    public void delete(String id) {
        exportDao.deleteByPrimaryKey(id);
    }


    // 根据远程调用结果，修改数据库（报运单状态、备注、商品交税金额）
    @Override
    public void updateByExportResult(ExportResult exportResult) {
        //1. 修改报运单（报运单状态、备注）
        Export export = new Export();
        export.setId(exportResult.getExportId());
        export.setState(exportResult.getState());
        export.setRemark(exportResult.getRemark());
        // 调用dao修改
        exportDao.updateByPrimaryKeySelective(export);

        //2. 修改报运单商品的交税金额
        Set<ExportProductResult> products = exportResult.getProducts();
        if (products != null && products.size() > 0) {
            for (ExportProductResult productResult : products) {
                // 根据商品的id修改交税金额
                ExportProduct exportProduct = new ExportProduct();
                exportProduct.setId(productResult.getExportProductId());
                exportProduct.setTax(productResult.getTax());
                exportProductDao.updateByPrimaryKeySelective(exportProduct);
            }
        }
    }

    @Override
    public List<Export> findAll(ExportExample exportExample) {
        return exportDao.selectByExample(exportExample);
    }


}














